﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using VietThinks.Website.Controllers;
using VietThinks.Web.Mvc;

namespace VietThinks.Website.ActionFilter
{
    public class RequestFilter : ActionFilterAttribute
    {
        public string IpWhitelist { get; set; }
        public string IpBlacklist { get; set; }

        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            var request = filterContext.HttpContext.Request;

            if ((!String.IsNullOrEmpty(IpBlacklist) && IsBlacklisted(request))
                || (!String.IsNullOrEmpty(IpWhitelist) && !IsWhitelisted(request))) 
            {
                string absoluteUri = request.Url.AbsoluteUri;
                var urlHelper = new UrlHelper(filterContext.RequestContext);
                filterContext.Result = new RedirectResult(urlHelper.ActionEx<ErrorController>(c => c.Forbidden(absoluteUri)));
                //shouldn't use below statment bc when go out this function and 
                //other place have a exception then system raise a exception "Cannot redirect after HTTP headers have been sent."
                //filterContext.HttpContext.Response.Redirect(urlHelper.ActionEx<ErrorController>(c => c.Forbidden(absoluteUri)),true);
            }
            else
            {
                base.OnActionExecuting(filterContext);
            }
        }

        protected bool IsBlacklisted(HttpRequestBase request)
        {
            var blacklistedIps = GetIpList(IpBlacklist);

            return blacklistedIps.Any(ip => ip.Equals(request.UserHostAddress));
        }

        protected bool IsWhitelisted(HttpRequestBase request)
        {
            var whitelistedIps = GetIpList(IpWhitelist);

            return whitelistedIps.Any(ip => request.UserHostAddress.StartsWith(ip.Replace("*", string.Empty)));
        }

        protected IList<string> GetIpList(string listName)
        {
            string ips = ConfigurationManager.AppSettings[listName];

            return ips != null
                    ? ips.Split(',')
                        .Where(ip => !String.IsNullOrEmpty(ip.Trim()))
                        .Select(ip => ip.Trim())
                        .ToList()
                    : new List<string>();
        }
    }
}
